<template>
  <div class="websocket">
    <!-- 在线客服聊天气泡消息 -->
    <ChatMessages ref="ChatMessages"></ChatMessages>
    <!-- 视频/语音余额不足 -->
    <NotEnoughDialog v-for="(v,i) in notEnoughDialogList" :not-enough-info="v" :key="v.bizId" :idx="i" @leaveRoom="leaveRoom" @closeNEDialog="closeNEDialog"></NotEnoughDialog>
  </div>
</template>

<script>
import md5 from 'js-md5';
import { cloneDeep } from 'lodash'
import { isDevelopment } from '@src/util/platform';
import { getRootWindowInitData } from '@src/util/window'
import * as ImApi from '@src/api/ImApi';
import { safeNewDate } from '@src/util/time';
import NF from 'src/util/NF.js'
import { playMusic } from '@src/util/index.ts'
/** components */
import NotEnoughDialog from './components/NotEnoughDialog.vue'
import ChatMessages from './components/ChatMessages.vue'

// 该websocket已被废弃，目前使用的是bizWebsocket组件(接收消息用了websocketOnMessage回调而已)
export default {
  name: 'global-web-socket',
  components:{
    NotEnoughDialog,
    ChatMessages
  },
  inject:['initData'],
  data() {
    return {
      websocket: null,
      isConnectIng: false, // 是否重连中
      currentTab: '', // 当前选中的tab
      envMap:{
        pubtest: {
          hostname: 'pubapp.shb.ltd',
        },
        test2: {
          hostname: 'test1.shb.ltd',
        },
        pre: {
          hostname: 'preapp.shouhoubao.net',
        },
        pre2: {
          hostname: 'pre2app.shb.ltd',
        },
        production: {
          hostname: 'app.shb.ltd',
        },
        multi_pre:{
          hostname: 'pctest.linker.ltd',
        },
        multi_prod:{
          hostname: 'cloud.shb.ltd',
        }
      },
      notEnoughDialogList:[], // 余额不足弹窗列表
    };
  },
  computed: {
    wsUrl() {
      // websocket连接地址
      const protocol = window.location.protocol === 'https:' ? 'wss' : 'wss';
      const ts = safeNewDate().getTime();
      const uid = this.initData.user.userId;
      const sign = this.getSign(ts, uid);
      const str = `ts=${ts}&userId=${uid}&sign=${sign}`;
      if(isDevelopment()){
        const {env} = getRootWindowInitData()
        console.log(env)
        const hostname = window.location.hostname || this.envMap[env].hostname
        return `${protocol}://${hostname}/api/im/notify/push/${str}`
      }
      return `${protocol}://${window.location.hostname}/api/im/notify/push/${str}`;
    },
  },
  created() {
    // 监听当前窗口是否是在线客服
    this.$eventBus.$on('watchTab', currentTab => {
      this.currentTab = currentTab
    });
  },
  mounted() {
    // this.initWebSocket();
  },
  methods: {
    // 初始化websocket
    initWebSocket() {
      // const wsuri = 'wss://socket.idcd.com:1443';
      this.websocket = new WebSocket(this.wsUrl);
      this.websocket.onmessage = this.websocketOnMessage;
      this.websocket.onopen = this.websocketOnOpen;
      this.websocket.onerror = this.websocketOnError;
      this.websocket.onclose = this.websocketClose;
    },
    // 连接建立回调
    websocketOnOpen() {
      console.info('客服消息推送webSocket连接成功');
    },

    // 连接建立失败重连
    websocketOnError() {
      console.info('客服消息推送webSocketk连接失败，尝试重新连接');
      this.reConnect(5000);
    },

    // 数据接收
    websocketOnMessage(res) {
      let data = res.data;
      try {
        if (typeof res.data == 'string') {
          data = JSON.parse(res.data);
        }
      } catch (e) {
        console.error('接收消息error', e);
      }
      // 心跳检测
      // if (data.data) {
      //   if (data.data.ping) {
      //     return this.websocketSend(JSON.stringify({pong:data.data.ping}));
      //   }
      //   return;
      // }
      let messageInfo = data || {}
      console.log(messageInfo)
      const { notifyType, content, titleName, pcUrl } = messageInfo
      // 系统消息
      if(notifyType == 'newSysMessage'){

        this.sysMessageFun(messageInfo)
      }

      /** **  气泡消息通知 ****/
      if(notifyType == 'newMessage'){
        // 注意：气泡消息会对messageInfo对象添加element消息组件实例属性，由于引用类型的特性，会影响postMessage传参，故用深拷贝
        this.newMessageCb(cloneDeep(messageInfo))
        this.im_sendWebNotification(messageInfo)
        playMusic()
      }
      /** 400电话通知-来自产品二维码电话咨询 */
      if(notifyType == 'productQrCodeCustomerAddLeavelMessage'){
        this.newMessageCb(cloneDeep(messageInfo))
      }
      if(notifyType == 'chatNewMessage' || notifyType == 'chatGroupNewMessage'){
        // 内部在线客服消息通知
        this.chatNewMessageCb(cloneDeep(messageInfo))
        playMusic()
      }
      // 在线客服新会话通知，会话转交，会话指派
      if(
        ['newConversation','forwardConversation','assignConversation'].includes(notifyType) 
        && !this.currentTab.currentUrl.includes('/im/imChat')
        && messageInfo?.content?.conversationId
      ) {
        this.chatNewMessageCb(cloneDeep(messageInfo))
        playMusic()
      }
      /** **  手动关闭视频页面tab ****/
      if(notifyType == 'manualFinishVideoRoom'){
        this.manualFinishVideoRoomCb(messageInfo)
      }
      /** **  视频/语音余额不足 ****/
      if(notifyType == 'closeAllVideoRoom'){
        this.notEnoughCb(messageInfo)
      }
      /** ** 组件通知  ****/
      if(notifyType == 'customerServiceStatus'){
        this.$eventBus.$emit('changeCustomerServiceStatus');
      }
      if(notifyType == 'callCenterSeatBindStatus'){
        // 绑定和解绑呼叫中心坐席
        this.$eventBus.$emit('bindingCallBack', messageInfo);
      }
      // 内部im组件接收
      if(['chatNewMessage', 'chatGroupNewMessage', 'chatNewGroup', 'groupDynamic'].includes(notifyType)){
        // 聊天窗口没打开不需要做处理
        if(sessionStorage.getItem('chatShow') != 1) return
        this.$eventBus.$emit('websocket_insideIm', messageInfo);
        // 测试用到时候删掉
        this.$eventBus.$emit('websocket_insideIm_chat', messageInfo);
      }
      // 通知客服休息
      if(notifyType == 'customer_service_off_work'){
        this.$eventBus.$emit('serviceOffWork');
      }

      if(notifyType === 'automaticWork') {
        this.$eventBus.$emit('serviceCallCenterAutomaticWork', content);
        this.newMessageCb(cloneDeep(messageInfo))
      }

      /** ** 页面通知  ****/
      if(this.isOpenWindow('/im/conversationLine')){
        let page = this.isOpenWindow('/im/conversationLine')
        page.contentWindow.postMessage({action:'shb.system.websocket', data:messageInfo}, '*');
      }
      if(this.isOpenWindow('/im/imChat')){
        let page = this.isOpenWindow('/im/imChat')
        page.contentWindow.postMessage({action:'shb.system.websocket', data:messageInfo}, '*');
      }
      if(this.isOpenWindow('/pcModule/customerServiceStatusList')){
        let page = this.isOpenWindow('/pcModule/customerServiceStatusList')
        page.contentWindow.postMessage({action:'shb.system.websocket', data:messageInfo}, '*');
      }
      if(this.isOpenWindow('/pcModule/callCenterServiceStatusList')){
        let page = this.isOpenWindow('/pcModule/callCenterServiceStatusList')
        page.contentWindow.postMessage({action:'shb.system.websocket', data:messageInfo}, '*');
      }
      if(this.isOpenWindow('/pcModule/setting/imSetting')){
        let page = this.isOpenWindow('/pcModule/setting/imSetting')
        page.contentWindow.postMessage({action:'shb.system.websocket', data:messageInfo}, '*');
      }
    },

    // 数据发送
    websocketSend(data) {
      this.websocket.send(data);
    },

    // 关闭
    websocketClose(e) {
      console.info('客服消息推送webSocket断开连接，尝试重新连接');
      this.reConnect(5000);
    },

    /**
     * reConnect 重新连接websocket
     * @param {number} time 连接间隔
     */
    reConnect(time) {
      if (this.isConnectIng) return;
      this.isConnectIng = true;
      setTimeout(() => {
        this.initWebSocket();
        this.isConnectIng = false;
      }, time);
    },
    /**
     * newMessageCb 处理newMessage类型回调
     * @param {object} messageInfo 消息体
     */
    newMessageCb(messageInfo){
      let CurrentCustomerInfor = JSON.parse(
        sessionStorage.getItem('CurrentCustomerInfor')
      );
        // 1.当前窗口是在线客服且消息是属于当前会话 则不推消息
      if (
        this.currentTab.currentUrl.includes('/im/imChat')
        && messageInfo.content.conversationId == CurrentCustomerInfor?.id
      )
        return;
        // 2.添加气泡消息
      this.$refs.ChatMessages.addMessage(messageInfo);
    },
    // 内部im新消息提示
    chatNewMessageCb(messageInfo){
      let chatShow = sessionStorage.getItem('chatShow')
      if (chatShow == 1) return;
      // 2.添加气泡消息
      this.$refs.ChatMessages.addMessage(messageInfo);
    },
    /**
     * notEnoughCb 处理视频/通话余额不足
     * @param {object} messageInfo 消息体
     */
    notEnoughCb(messageInfo){
      if(this.notEnoughDialogList.length < 1){
        // 目前只接收一个视频结束弹窗
        console.log('第一个弹窗')
        this.notEnoughDialogList.push({...messageInfo, dialogVisible:true})
      }
    },
  
    /**
     * isOpenWindow 判断某窗口是否打开
     * @param {string} url 窗口路径例如 /im/imChat
     * @return {dom} page 窗口dom对象
     */
    isOpenWindow(url){
      let page;
      let iframes = Array.from(document.getElementsByTagName('iframe'));
      page = iframes.find(item =>item.src.includes(url))
      return page
    },
    getSign(ts, uid) {
      let str = `ts=${ts}&userId=${uid}SHOU_HOU_BAO`;
      return md5(str);
    },
   
    /**
     * 离开房间
     */
    async leaveRoom(payload){
      let {data, idx} = payload
      const params = data?.content || {}
      try{
        const {code, message} = await ImApi.leaveRoom(params)
        if(code == 0){
          this.closeVideoPage()
          this.notEnoughDialogList = []
        }else{
          console.log('关闭视频房间错误', message)
        }
      }finally{
        this.closeNEDialog(idx)
      }
    },
    // 关闭视频余额弹窗
    closeNEDialog(idx){
      this.notEnoughDialogList[idx].dialogVisible = false
    },
    // 关闭视频tab
    closeVideoPage(){
      let iframes = Array.from(document.getElementsByTagName('iframe'));
      let videosRooms = iframes.filter(item =>item.id.includes('VIDEOCUSTOMER'))
      videosRooms.map(page=>{
        if(page){
          let id = page.dataset.id
          this.$platform.closeTab(id)
        }
      })
    },
    // 手动关闭视频通知回调关闭tab页面
    manualFinishVideoRoomCb(messageInfo){
      const roomNumber = messageInfo.content.roomNumber
      let iframes = Array.from(document.getElementsByTagName('iframe'));
      let videosRooms = iframes.filter(item =>item.id.includes('VIDEOCUSTOMER'))
      let page = videosRooms.find((item=>item.id.includes(roomNumber)))
      if(page){
        let id = page.dataset.id
        this.$platform.closeTab(id)
      }
    },
    // 发送浏览器消息通知
    im_sendWebNotification(info){
      if(document?.visibilityState != 'hidden') return
      // 页面对用户不可见发送浏览器通知
      let title = ''
      let body = ''
      let messageType = ''
      let messageFrom = ''
      const content = info.content
      messageType = content.messageType
      messageFrom = content.messageFrom
      title = info.titleName
      if(messageType=='txt'){
        body = `${messageFrom}：${content.messageContent.msg}`
      }else{
        body = `${messageFrom}：你有一条新消息`
      }
      new NF({
        title,
        body,
        click:function(){
          window.focus()
          this.shut()
        }
      })
    },

    // 气泡消息卡片点击回调
    messageClick(notification, info) {
      
      const { pcUrl, source, tag } = info

      if(!pcUrl || source === 'calendar') return;

      let pageId = this.getId(info);

      const defaultTitleMap = {
        'exchange': '表单详情',
        'satisfaction': '问卷详情',
      };

      let title = info.title ? info.title : defaultTitleMap[info.source] || '正在查询';

      if(tag === 'qrcode') title = '超级二维码行为分析';

      this.$platform.openTab({
        id: pageId,
        title,
        close: true,
        url: pcUrl
      });

      // 2.销毁气泡消息
      notification.close();
    },
    
    // 系统消息通知
    sysMessageFun(messageInfo){
      const { notifyType, content, titleName, pcUrl} = messageInfo
      let notification = this.$notify({
        title:titleName,
        dangerouslyUseHTMLString: true,
        message: `<div class="messageInfo">${content}</div>`,
        duration: 5000,
        customClass: 'customer-service-message-push',
        onClick: () => {
          this.messageClick(notification, messageInfo)
        }
      });
      
      if(document?.visibilityState != 'hidden') return
      let self = this
      // 浏览器消息通知
      new NF({
        title:titleName,
        body:content,
        requireInteraction:false,
        tag:pcUrl,
        click:function(){
          window.focus()
          this.shut()

          let pageId = self.getId(messageInfo);
          let openTapParams = {
            id: pageId,
            title:'正在查询',
            close: true,
            url: pcUrl
          }
          // 判断是否是跳转到paas的详情页面 需要刷新
          if(pcUrl.includes('/paas/#/')) {
            openTapParams.reload = true
            openTapParams.viewType = 'vue'
          }

          self.$platform.openTab(openTapParams);
        }
      })
    },

    // 从src/modules/system/frame/component/notificationCenter/JobNotificationItem.vue拷贝过来的
    getId(info) {
      const { pcUrl, primaryId } = info
      // pcUrl=/security/user?ranKey=123456&select=delete

      const { id } = this.$getUrlObj({
        location:{
          href:pcUrl
        }
      })

      // 结算单详情
      if (pcUrl.includes('/pcResourceManage/settleDetailView')) return `settle_view_${id}`;

      // 订购单详情
      if(pcUrl.includes('/purchaaseOrderManage/view')) return `purchaaseOrderManageView${id}`;
      // 服务商详情
      if(pcUrl.includes('/service/manage/provider/detail')) return `service_provider_detail_${id}`;
      // 工程师详情
      if(pcUrl.includes('/service/manage/engineer/detail')) return `service_engineer_detail_${id}`;

      if (pcUrl.includes('/security/user')) return 'M_JOBTRANSFER_DETAIL';

      if (pcUrl.includes('/task/view/')) return `task_view_${primaryId}`;

      if (pcUrl.includes('/partV2/repertory/record')) return 'M_VIP_SPAREPART_RECORD';

      if (pcUrl.includes('/event/view/')) return 'M_SERVICE_PROJECT';

      if (pcUrl.includes('/info/notice/detail/page')) return `bulletin_detail_${primaryId}`;
      
      if (pcUrl.includes('/wiki/detail/page')) return `document_detail_${primaryId}`;

      if (pcUrl.includes('/im/imChat')) return 'M_CHILD_ONLINE_CUSTOMER_SERVICE';

      if (pcUrl.includes('/calendar')) return 'M_CALENDAR_ALL';

      if (pcUrl.includes('/product/bhAnalysis')) return 'M_QRCODE_ANALYSIS';

      if (pcUrl.includes('/home') || pcUrl.includes('/foundation/workBench')) return 'M_HOME';

      return 'PcUrl';
    }
  },
};
</script>

<style scoped lang="scss">
.websocket {
  height: 0;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 9999;
}
.customer-service-message-push {
  cursor: pointer;
  background: linear-gradient(109deg, #DFF8F4 0%, #FFFFFF 100%);
  .el-notification__group {
    width: 100%;
    .el-notification__title {
      font-size: 14px;
      font-family: PingFangSC-Regular, PingFang SC;
      font-weight: 400;
      color: #262626;
      line-height: 14px;
    }
    .el-notification__content {
      width: 100%;
    }
  }
  .messageInfo {
    font-size: 16px;
    font-weight: bold;
    width: 100%;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
}
</style>

